using System;
namespace ch.ethz.ssh2.crypto
{
	
	/// <summary> Basic Base64 Support.
	/// 
	/// </summary>
	/// <author>  Christian Plattner
	/// </author>
	/// <version>  2.50, 03/15/10
	/// </version>
	public class Base64
	{
		internal static readonly char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".ToCharArray();
		
		public static char[] encode(byte[] content)
		{
			System.IO.StringWriter cw = new System.IO.StringWriter();
			
			int idx = 0;
			
			int x = 0;
			
			for (int i = 0; i < content.Length; i++)
			{
				if (idx == 0)
					x = (content[i] & 0xff) << 16;
				else if (idx == 1)
					x = x | ((content[i] & 0xff) << 8);
				else
					x = x | (content[i] & 0xff);
				
				idx++;
				
				if (idx == 3)
				{
					cw.Write(alphabet[x >> 18]);
					cw.Write(alphabet[(x >> 12) & 0x3f]);
					cw.Write(alphabet[(x >> 6) & 0x3f]);
					cw.Write(alphabet[x & 0x3f]);
					
					idx = 0;
				}
			}
			
			if (idx == 1)
			{
				cw.Write(alphabet[x >> 18]);
				cw.Write(alphabet[(x >> 12) & 0x3f]);
				cw.Write('=');
				cw.Write('=');
			}
			
			if (idx == 2)
			{
				cw.Write(alphabet[x >> 18]);
				cw.Write(alphabet[(x >> 12) & 0x3f]);
				cw.Write(alphabet[(x >> 6) & 0x3f]);
				cw.Write('=');
			}
			
			return cw.ToString().ToCharArray();
		}
		
		public static byte[] decode(char[] message)
		{
			byte[] buff = new byte[4];
			byte[] dest = new byte[message.Length];
			
			int bpos = 0;
			int destpos = 0;
			
			for (int i = 0; i < message.Length; i++)
			{
				int c = message[i];
				
				if ((c == '\n') || (c == '\r') || (c == ' ') || (c == '\t'))
					continue;
				
				if ((c >= 'A') && (c <= 'Z'))
				{
					buff[bpos++] = (byte) (c - 'A');
				}
				else if ((c >= 'a') && (c <= 'z'))
				{
					buff[bpos++] = (byte) ((c - 'a') + 26);
				}
				else if ((c >= '0') && (c <= '9'))
				{
					buff[bpos++] = (byte) ((c - '0') + 52);
				}
				else if (c == '+')
				{
					buff[bpos++] = 62;
				}
				else if (c == '/')
				{
					buff[bpos++] = 63;
				}
				else if (c == '=')
				{
					buff[bpos++] = 64;
				}
				else
				{
					throw new System.IO.IOException("Illegal char in base64 code.");
				}
				
				if (bpos == 4)
				{
					bpos = 0;
					
					if (buff[0] == 64)
						break;
					
					if (buff[1] == 64)
						throw new System.IO.IOException("Unexpected '=' in base64 code.");
					
					if (buff[2] == 64)
					{
						int v = (((buff[0] & 0x3f) << 6) | ((buff[1] & 0x3f)));
						dest[destpos++] = (byte) (v >> 4);
						break;
					}
					else if (buff[3] == 64)
					{
						int v = (((buff[0] & 0x3f) << 12) | ((buff[1] & 0x3f) << 6) | ((buff[2] & 0x3f)));
						dest[destpos++] = (byte) (v >> 10);
						dest[destpos++] = (byte) (v >> 2);
						break;
					}
					else
					{
						int v = (((buff[0] & 0x3f) << 18) | ((buff[1] & 0x3f) << 12) | ((buff[2] & 0x3f) << 6) | ((buff[3] & 0x3f)));
						dest[destpos++] = (byte) (v >> 16);
						dest[destpos++] = (byte) (v >> 8);
						dest[destpos++] = (byte) (v);
					}
				}
			}
			
			byte[] res = new byte[destpos];
			Array.Copy(dest, 0, res, 0, destpos);
			
			return res;
		}
	}
}